// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_WASM_FUZZING_RANDOM_MODULE_GENERATION_H_
#define V8_WASM_FUZZING_RANDOM_MODULE_GENERATION_H_

#if !V8_ENABLE_WEBASSEMBLY
#error This header should only be included if WebAssembly is enabled.
#endif  // !V8_ENABLE_WEBASSEMBLY

#include "src/base/enum-set.h"
#include "src/base/export-template.h"
#include "src/base/logging.h"
#include "src/base/vector.h"
#include "src/wasm/wasm-module.h"

namespace v8::internal {
class Zone;
}

namespace v8::internal::wasm::fuzzing {

#ifdef V8_WASM_RANDOM_FUZZERS
// Defines what expressions should be generated by the fuzzer besides the MVP
// ones.
enum WasmModuleGenerationOption { kGenerateSIMD, kGenerateWasmGC };

struct ExportData {
  std::string name;
  const FunctionSig* sig;
  ModuleTypeIndex sig_index;
  std::string module_name;
  uint32_t index = 0;

  ExportData(std::string name, const FunctionSig* sig,
             std::string module_name = "", uint32_t index = 0)
      : name(std::move(name)),
        sig(sig),
        module_name(std::move(module_name)),
        index(index) {}
};

struct WasmModuleGenerationOptions
    : public base::EnumSet<WasmModuleGenerationOption> {
  // Implicitly construct from a `base::EnumSet` (this allows to use `EnumSet`'s
  // operators on a `WasmModuleGenerationOptions` object).
  constexpr WasmModuleGenerationOptions(
      base::EnumSet<WasmModuleGenerationOption> options)
      : base::EnumSet<WasmModuleGenerationOption>(options) {}

  bool generate_simd() const { return contains(kGenerateSIMD); }
  bool generate_wasm_gc() const { return contains(kGenerateWasmGC); }

  static constexpr WasmModuleGenerationOptions MVP() { return {{}}; }
  static constexpr WasmModuleGenerationOptions Simd() {
    return {{kGenerateSIMD}};
  }
  static constexpr WasmModuleGenerationOptions WasmGC() {
    return {{kGenerateWasmGC}};
  }
  static constexpr WasmModuleGenerationOptions All() {
    return {{kGenerateSIMD, kGenerateWasmGC}};
  }
};

// Generate a valid Wasm module based on the given input bytes.
// Returns an empty buffer on failure, valid module wire bytes otherwise.
// The bytes will be allocated in the zone.
// Defined in random-module-generation.cc.
V8_EXPORT_PRIVATE base::Vector<uint8_t> GenerateRandomWasmModule(
    Zone*, WasmModuleGenerationOptions, base::Vector<const uint8_t> data,
    std::vector<ExportData>* exports = nullptr,
    std::vector<ExportData>* imports = nullptr);

V8_EXPORT_PRIVATE base::Vector<uint8_t> GenerateWasmModuleForInitExpressions(
    Zone*, base::Vector<const uint8_t> data, size_t* count);

V8_EXPORT_PRIVATE base::Vector<uint8_t> GenerateWasmModuleForDeopt(
    Zone*, base::Vector<const uint8_t> data, std::vector<std::string>& callees,
    std::vector<std::string>& inlinees);

V8_EXPORT_PRIVATE base::Vector<uint8_t> GenerateWasmModuleForRevec(
    Zone*, base::Vector<const uint8_t> data);
#endif

}  // namespace v8::internal::wasm::fuzzing

#endif  // V8_WASM_FUZZING_RANDOM_MODULE_GENERATION_H_
